import json
from markdown import markdown
import os
from datetime import datetime

def filter(a):
	ret = ""
	for i in a:
		if i.isalnum():
			ret += i
	return ret

def loadFile(fnm):
	try:
		f = open(fnm, "r", encoding="UTF-8")
		ret = f.read()
		f.close()
	except:
		ret = ""
	return ret

def saveFile(fnm, val):
	f = open(fnm, "w", encoding="UTF-8")
	f.write(val)
	f.close()
	
def saveToDir(path, val):
	tmp = path[:path.rindex("/")]
	if not os.path.isdir(tmp):
		os.makedirs(tmp)
	saveFile(path, val)

class Blog(object):
	def __init__(self, title="", content="", date="", tags=[], categ="", headline=""):
		self.title = title
		self.content = content
		self.date = date
		self.tags = tags
		self.categ = categ
		self.link = ""
		self.tagRefs = []
		self.categRef = None
		self.headline = filter(headline)
		self.compiled = ""
	def getHTML(self):
		if self.compiled != "":
			return self.compiled
		else:
			return markdown(self.content)
	def getDesc(self):
		ret = ""
		for i in self.content:
			if ord(i) > 128 or i.isalnum():
				ret += i
		return ret[:100] + " ... Read More ..."
	def getCard(self):
		rdr = Render("source/template/blogCard.html")
		tmp = ""
		for i in self.tagRefs:
			tmp += i.getTag() + "&nbsp;"
		return rdr.render({"$TITLE": self.title, "$DESC": self.getDesc(), "$TAGS": str(tmp), "$LINK": self.link, "$DATE": self.date, "$CATEGNAME": self.categRef.name, "$CATEGLINK": self.categRef.link, "$HOME": "../"})
	def getPage(self):
		rdr = Render("source/template/blogPage.html")
		return rdr.render({"$CARD": self.getCard(), "$CONTENT": self.getHTML()})
	def __le__(self, rhs):
		return dateLater(self, rhs)
	
class Categ(object):
	def __init__(self, name="", desc="", headline=""):
		self.name = name
		self.desc = desc
		self.count = 0
		self.link = ""
		self.blogRefs = []
		self.headline = filter(headline)
		self.lastUpdate = "1949-10-01"
	def getCard(self):
		rdr = Render("source/template/categCard.html")
		return rdr.render({"$NAME": self.name, "$DESC": self.desc, "$LINK": self.link, "$BLOGCOUNT": str(self.count), "$HOME": "../"})
	def getPage(self):
		rdr = Render("source/template/categPage.html")
		tmp = ""
		for i in self.blogRefs:
			tmp += i.getCard()
		return rdr.render({"$CARD": self.getCard(), "$BLOGS": str(tmp), "$BLOGCOUNT": str(self.count), "$HOME": "../"})

class Tag(object):
	def __init__(self, name="", headline=""):
		self.count = 0
		self.name = name
		self.blogRefs = []
		self.link = ""
		self.headline = headline
	def getTag(self):
		return Render("source/template/tagLabel.html").render({"$NAME": self.name, "$HOME": "../"})
	def getCard(self):
		return Render("source/template/tagCard.html").render({"$NAME": self.name, "$COUNT": str(self.count), "$HOME": "../"})
	def getPage(self):
		rdr = Render("source/template/tagPage.html")
		tmp = ""
		for i in self.blogRefs:
			tmp += i.getCard()
		return rdr.render({"$CARD": self.getCard(), "$BLOGS": str(tmp)})

class Render(object):
	def __init__(self, fnm="", T=""):
		if T != "":
			self.template = T
			return
		if fnm == "":
			self.template = ""
		else:
			self.load(fnm)
	def load(self, fnm):
		self.template = loadFile(fnm)
	def clear(self):
		self.template = ""
	def render(self, m):
		ret = self.template
		for i in m:
			ret = ret.replace(i, m[i])
		return ret
	
def dateLater(a, b):
	if datetime.fromisoformat(a) > datetime.fromisoformat(b):
		return a
	return b
	
if __name__ == "__main__":
	# workspace Initialization
	toPath = "output/"
	#os.removedirs(toPath)
	
	# generate Object
	blogList = []
	blogMap = {}
	blogCfg = json.loads(loadFile("source/blog.json"))["Blog"]
	for i in blogCfg:
		a = Blog(i["title"], loadFile("source/post/" + i["filename"]), i["date"], i["tags"], i["category"], i["headline"])
		a.compiled = loadFile(("source/post/" + i["filename"])[:-2] + 'html')
		blogList += [a]
		blogMap[i["title"]] = a

	categList = []
	categMap = {}
	categCfg = json.loads(loadFile("source/categ.json"))["Categ"]
	for i in categCfg:
		a = Categ(i["name"], i["description"], i["headline"])
		categList += [a]
		categMap[i["name"]] = a

	tagList = []
	tagMap = {}
	tagCfg = json.loads(loadFile("source/tag.json"))["Tag"]
	for i in tagCfg:
		a = Tag(i["name"], i["headline"])
		tagList += [a]
		tagMap[i["name"]] = a

	# generate Ref
	for i in blogList:
		i.categRef = categMap[i.categ]
		i.categRef.count += 1
		i.categRef.blogRefs += [i]
		i.categRef.lastUpdate = dateLater(i.categRef.lastUpdate, i.date)
		for j in i.tags:
			ref = tagMap[j]
			ref.count += 1
			ref.blogRefs += [i]
			i.tagRefs += [ref]
			
	blogList.sort(key = lambda x: datetime.fromisoformat(x.date), reverse = True) # The first one is the latest
	categList.sort(key = lambda x: datetime.fromisoformat(x.lastUpdate), reverse = True) # The first one is the latest

	# generate Link
	for i in blogList:
		i.link = "blog/" + i.headline + ".html"
	for i in categList:
		i.link = "categ/" + i.headline + ".html"
	for i in tagList:
		i.link = "tag/" + i.headline + ".html"
	
	# generate Page (Basic)
	frame = Render("source/template/frame.html")
	sideBar = Render("source/template/sidebar.html")

	firstBlogTitle = secondBlogTitle = thirdBlogTitle = ""
	firstBlogLink = secondBlogLink = thirdBlogLink = ""
	if len(blogList) >= 1:
		firstBlogTitle = blogList[0].title
		firstBlogLink = blogList[0].link
	if len(blogList) >= 2:
		secondBlogTitle = blogList[1].title
		secondBlogLink = blogList[1].link
	if len(blogList) >= 3:
		thirdBlogTitle = blogList[2].title
		thirdBlogLink = blogList[2].link

	firstCategName = secondCategName = thirdCategName = ""
	firstCategLink = secondCategLink = thirdCategLink = ""
	if len(categList) >= 1:
		firstCategName = categList[0].name
		firstCategLink = categList[0].link
	if len(categList) >= 2:
		secondCategName = categList[1].name
		secondCategLink = categList[1].link
	if len(categList) >= 3:
		thirdCategName = categList[2].name
		thirdCategLink = categList[2].link

	cfg = {
		"$FIRSTBLOGTITLE": firstBlogTitle,
		"$FIRSTBLOGLINK": firstBlogLink,
		"$SECONDBLOGTITLE": secondBlogTitle,
		"$SECONDBLOGLINK": secondBlogLink,
		"$THIRDBLOGTITLE": thirdBlogTitle,
		"$THIRDBLOGLINK": thirdBlogLink,
		"$BLOGCOUNT": str(len(blogList)),
		"$CATEGCOUNT": str(len(categList)),
		"$TAGCOUNT": str(len(tagList)),
		"$FIRSTCATEGNAME": firstCategName,
		"$FIRSTCATEGLINK": firstCategLink,
		"$SECONDCATEGNAME": secondCategName,
		"$SECONDCATEGLINK": secondCategLink,
		"$THIRDCATEGNAME": thirdCategName,
		"$THIRDCATEGLINK": thirdCategLink
	}

	sideBar = Render(T = sideBar.render(cfg))
	
	# generate MainPage
	mainPage = Render("source/template/main.html")
	saveToDir("output/index.html", frame.render({"$HOME": "", "$CONTENT": mainPage.render({}), "$PAGETITLE": "ZCY的博客呀~", "$SIDEBAR": sideBar.render({"$HOME": ""})}))
	
	# generate BlogList
	tmp = ""
	for i in blogList:
		tmp += i.getCard()
	saveToDir(toPath + "blog/index.html", frame.render({"$HOME": "../", "$CONTENT": tmp, "$PAGETITLE": "博客列表", "$SIDEBAR": sideBar.render({"$HOME": "../"})}))
	
	# generate Blog
	for i in blogList:
		saveToDir(toPath + i.link, frame.render({"$HOME": "../", "$CONTENT": i.getPage(), "$PAGETITLE": i.title, "$SIDEBAR": sideBar.render({"$HOME": "../"})}))
	
	# generate CategList
	tmp = ""
	for i in categList:
		tmp += i.getCard()
	saveToDir(toPath + "categ/index.html", frame.render({"$HOME": "../", "$CONTENT": tmp, "$PAGETITLE": "分类列表", "$SIDEBAR": sideBar.render({"$HOME": "../"})}))
	
	# generate Categ
	for i in categList:
		saveToDir(toPath + i.link, frame.render({"$HOME": "../", "$CONTENT": i.getPage(), "$PAGETITLE": i.name, "$SIDEBAR": sideBar.render({"$HOME": "../"})}))

	# generate Tag
	for i in tagList:
		saveToDir(toPath + i.link, frame.render({"$HOME": "../", "$CONTENT": i.getPage(), "$PAGETITLE": i.name, "$SIDEBAR": sideBar.render({"$HOME": "../"})}))
